﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using Plugins.Historical;
using StockModel;
using System.Threading.Tasks;

namespace Plugins.Base.Historical
{
	public abstract class HistoricalEngineParallelBase : HistoricalEngineBase
	{
		#region Attributes

		private readonly object _executedDaysLock;

		#endregion

		#region Public Methods

		protected HistoricalEngineParallelBase(QuotationDataSource quotationDataSource, RawStockDataSource rawStockDataSource)
			: base(quotationDataSource, rawStockDataSource)
		{
			_executedDaysLock = new object();
		}

		public override void Execute()
		{
			try
			{
				List<KeyValuePair<DateTime, Tuple<List<Operation>, List<FrameworkElement>>>> tempData = new List<KeyValuePair<DateTime, Tuple<List<Operation>, List<FrameworkElement>>>>();

				base.InitializeEngine();

				List<HistoricalItemToProcess> itemsToProcess = this.FindItemsToProcess();
				base.TotalDaysToExecute = itemsToProcess.Count;

				Parallel.ForEach(itemsToProcess, historicalItemToProcess =>
				{
					using (HistoricalDayProcessorBase processor = this.CreateDayProcessor())
					{
						processor.ProcessHistoricalItem(historicalItemToProcess);
						lock (_executedDaysLock)
						{
							base.ExecutedDays++;
							tempData.Add(new KeyValuePair<DateTime, Tuple<List<Operation>, List<FrameworkElement>>>(historicalItemToProcess.Date, new Tuple<List<Operation>, List<FrameworkElement>>(processor.Operations, processor.CustomData)));
						}
					}
				});

				foreach (var tempItem in tempData.OrderBy(o => o.Key))
				{
					this.Operations.AddRange(tempItem.Value.Item1);
					this.CustomData.AddRange(tempItem.Value.Item2);
				}

				this.OnResultsAvailable(this.Operations, this.CustomData);
			}
			finally
			{
				this.ClearEngine();
			}
		}

		#endregion
	}
}
